﻿using Dapper;
using System;
using System.Threading.Tasks;
using Loong.Dapper;
using Loong.Dapper.DbAccessors;
using Loong.Dapper.Filters.Action;
using Loong.Dapper.Filters.Query;

namespace Loong.BackgroundJobs
{
    public class BackgroundJobDbAccessor : DapperDbAccessorBase<BackgroundJobInfo, long>, IBackgroundJobDbAccessor
    {
        public BackgroundJobDbAccessor(
            IActiveTransactionProvider activeTransactionProvider,
            IDapperQueryFilterExecuter dapperQueryFilterExecuter,
            IDapperActionFilterExecuter dapperActionFilterExecuter)
            : base(activeTransactionProvider, dapperQueryFilterExecuter, dapperActionFilterExecuter)
        { }

        public async Task<BackgroundJobInfo> GetWaitingJobAsync()
        {
            string sql = @"
select
*
from BackgroundJob
where IsAbandoned=0
and NextTryTime<=@now
and (IsLocked=0 or (IsLocked=1 and LockEndTime<=@now))
order by Priority desc,TryCount,NextTryTime
limit 1 for update
";
            return await Connection.QueryFirstOrDefaultAsync<BackgroundJobInfo>(sql, new { now = DateTime.Now }, Transaction);
        }

        public async Task<bool> LockJobAsync(BackgroundJobInfo jobInfo)
        {
            string sql = @"
update BackgroundJob set
IsLocked=1,
LockEndTime=@LockEndTime
where Id=@Id
";
            return (await Connection.ExecuteAsync(sql, new { jobInfo.Id, jobInfo.LockEndTime }, Transaction)) > 0;
        }
    }
}
